package com.hsd.znsh.service;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hsd.znsh.entity.Gateway;
import com.hsd.znsh.entity.Sensor;
import com.hsd.znsh.properties.MqttProperties;
import com.hsd.znsh.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/*
 * @auther: wangjiacai
 *
 * @create: 2018-06-25 15:07:02
 */
@Service
public class LoraService {

    @Autowired
    private MqttProperties mqttProperties;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RestTemplate restTemplate;

    private String deviceProfileID;

    private String networkServerID;

    private String jwt;

    private LocalDateTime time;


    /*登录获取jwt*/
    private void login(){
        if (this.jwt == null || (this.jwt != null && isExpired())) {
            String url = mqttProperties.getIp()+"/api/internal/login";
            Map request = new HashMap();
            request.put("username", mqttProperties.getLoraUsername());
            request.put("password", mqttProperties.getLoraPassword());
            String response=restTemplate.postForObject(url,request,String.class);
            this.jwt= JSONObject.parseObject(response).getString("jwt");
            this.time=LocalDateTime.now();
        }
    }

    private HttpEntity<Object> getHeader(){
        MultiValueMap<String,String> header=new LinkedMultiValueMap<>();
        header.set("Authorization",this.jwt);
        HttpEntity<Object> httpEntity=new HttpEntity<>(header);
        return httpEntity;
    }

    private HttpEntity<Object> getHeader(Map request){
        MultiValueMap<String,String> header=new LinkedMultiValueMap<>();
        header.set("Authorization",this.jwt);
        HttpEntity<Object> httpEntity=new HttpEntity<>(request,header);
        return httpEntity;
    }

    /*token是否失效*/
    private boolean isExpired(){
        if(this.time.plusHours(23).isBefore(LocalDateTime.now())) return true;
        return false;
    }

    public String getNetworkServerID(){
        login();
        String url=mqttProperties.getIp()+"/api/network-servers?limit=99&offset=0&organizationID="+mqttProperties.getOrganizationID();
        HttpEntity<Object> httpEntity=this.getHeader();
        HttpEntity<String> response=restTemplate.exchange(url, HttpMethod.GET,httpEntity,String.class);
        JSONArray jsonArray=JSONObject.parseObject(response.getBody()).getJSONArray("result");
        this.networkServerID=jsonArray.getJSONObject(0).getString("id");
        return this.networkServerID;
    }

    /*获取deviceProfileID*/
    public String getDeviceProfileID(){
        login();
        String url=mqttProperties.getIp()+"/api/device-profiles?limit=99&offset=0&applicationID="+mqttProperties.getApplicationID();
        HttpEntity<Object> httpEntity=this.getHeader();
        HttpEntity<String> response=restTemplate.exchange(url, HttpMethod.GET,httpEntity,String.class);
        JSONArray jsonArray=JSONObject.parseObject(response.getBody()).getJSONArray("result");
        this.deviceProfileID=jsonArray.getJSONObject(0).getString("deviceProfileID");
        return this.deviceProfileID;
    }

    public boolean addGateway(Gateway gateway){
        try{
            if (this.networkServerID == null) getNetworkServerID();
            String url=mqttProperties.getIp()+"/api/gateways";
            Map request=new HashMap();
            request.put("networkServerID",this.networkServerID);
            request.put("description",gateway.getName());
            request.put("mac",gateway.getGatewayId());
            request.put("name",gateway.getName());
            request.put("organizationID",mqttProperties.getOrganizationID());
            request.put("ping",true);
            HttpEntity<Object> httpEntity=this.getHeader(request);
            restTemplate.exchange(url,HttpMethod.POST,httpEntity,String.class);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }



    public boolean addDevice(Sensor sensor)  {
        try{
            if(this.deviceProfileID==null) getDeviceProfileID();
            String url=mqttProperties.getIp()+"/api/devices";
            Map request=new HashMap();
            request.put("applicationID",mqttProperties.getApplicationID());
            request.put("description",sensor.getName());
            request.put("devEUI",sensor.getSensorSn());
            request.put("deviceProfileID",this.deviceProfileID);
            request.put("name",sensor.getName());
            request.put("skipFCntCheck",true);
            HttpEntity<Object> httpEntity=this.getHeader(request);
            restTemplate.exchange(url,HttpMethod.POST,httpEntity,String.class);

            if(!addDeviceKeys(sensor.getSensorSn())){
                while(!deleteDevice(sensor.getSensorSn())){
                    Thread.sleep(1000);
                }
                return false;
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean addDeviceKeys(String devEUI){
        try {
            login();
            String keyUrl=mqttProperties.getIp()+"/api/devices/{devEUI}/keys";
            Map request=new HashMap();
            Map deviceKeys=new HashMap();
            deviceKeys.put("appKey","2b7e151628aed2a6abf7158809cf4f3c");
            request.put("deviceKeys",deviceKeys);
            MultiValueMap<String,String> header=new LinkedMultiValueMap();
            header.set("Authorization",this.jwt);
            HttpEntity<Object> httpEntity=new HttpEntity<>(objectMapper.writeValueAsString(request),header);
            restTemplate.exchange(keyUrl,HttpMethod.POST,httpEntity,String.class,devEUI);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean deleteDevice(String devEUI){
        try{
            login();
            String url=mqttProperties.getIp()+"/api/devices/{devEUI}";
            HttpEntity<Object> httpEntity=this.getHeader();
            restTemplate.exchange(url,HttpMethod.DELETE,httpEntity,String.class,devEUI);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean deleteGateway(String gatewayId){
        try{
            login();
            String url=mqttProperties.getIp()+"/api/gateways/{gatewayId}";
            HttpEntity<Object> httpEntity=this.getHeader();
            restTemplate.exchange(url,HttpMethod.DELETE,httpEntity,String.class,gatewayId);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public Date getDeviceLastDate(String devEUI){
        try{
            login();
            String url=mqttProperties.getIp()+"/api/devices/{devEUI}";
            HttpEntity<Object> httpEntity=this.getHeader();
            ResponseEntity<String> response=restTemplate.exchange(url,HttpMethod.GET,httpEntity,String.class,devEUI);
            JSONObject jsonObject=JSONObject.parseObject(response.getBody());
            String timeStr=jsonObject.getString("lastSeenAt");
            if(StringUtils.isEmpty(timeStr)) return null;
            timeStr= timeStr.substring(0,timeStr.lastIndexOf("+")-3);
            return DateUtil.parse(timeStr,"yyyy-MM-dd'T'HH:mm:ss.SSS");
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public Date getGatewayLastDate(String gatewayId){
        try{
            login();
            String url=mqttProperties.getIp()+"/api/gateways/{gatewayId}";
            HttpEntity<Object> httpEntity=this.getHeader();
            ResponseEntity<String> response=restTemplate.exchange(url,HttpMethod.GET,httpEntity,String.class,gatewayId);
            JSONObject jsonObject=JSONObject.parseObject(response.getBody());
            String timeStr=jsonObject.getString("lastSeenAt");
            if(StringUtils.isEmpty(timeStr)) return null;
            timeStr= timeStr.substring(0,timeStr.lastIndexOf("+")-3);
            return DateUtil.parse(timeStr,"yyyy-MM-dd'T'HH:mm:ss.SSS");
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

}

